/**
 * @file CRectangle.cpp
 * @author redfrogotr
 * @brief 利用一个平面点类CPoint设计矩形类CRectangle类
 * @date 2022-04-03
 */

#include <iostream>
#include <cstdio>   // printf
#include <cmath>    // sqrt, pow

using namespace std;

class CPoint
{
private:
    double x, y;    // the x and y coordinates of point

public:
    CPoint(double x = 0, double y = 0) : x(x), y(y) {}
    void setX(double x) { this->x = x; }
    double getX() { return x; }
    void setY(double y) { this->y = y; }
    double getY() { return y; }
    double distance(const CPoint& point) {
        return sqrt(pow(x - point.x, 2) + pow(y - point.y, 2));
    }
    void print() const {
        printf("(%.2lf,%.2lf)\n", x, y);
    }
};

class CRectangle
{
private:
    CPoint tlPoint, brPoint;    // top left point, bottom right point
    double length;  // long side
    double width;   // short side
    int type;       // 0: non-rectangle, 1: square, 2: rectangle
    static int num; // the number of current rectangles
    
public:
    explicit CRectangle(CPoint p1, CPoint p2) : tlPoint(p1), brPoint(p2) {
        width = p2.getX() - p1.getX();
        length = p1.getY() - p2.getY();
        if (width <= 0 || length <= 0) {
            type = 0;
        } else {
            num++;
            if (length == width) {
                type = 1;
            } else {
                type = 2;
                if (width > length) {   // swap
                    double tmp = width;
                    width = length;
                    length = tmp;
                }
            }
        }
    }
    ~CRectangle() {
        if (type > 0) num--;
    }
    double getLength() { return type > 0 ? length : 0; }
    double getWidth() { return type > 0 ? width : 0; }
    double getArea() { return type > 0 ? length * width : 0; }
    int getType() { return type; }
    char* getTypeDescription() {
        if (type == 0) return "NON-rectangle";
        if (type == 1) return "SQUARE";
        return "RECTANGLE";
    }
    static int showCount() { return num; }
};
int CRectangle::num = 0;

ostream& operator<<(ostream& out, CRectangle& rec) {
    if (rec.getType() > 0) {
        out << "length is " << rec.getLength() << ", "
            << "width is " << rec.getWidth() << ", "
            << rec.getTypeDescription() << ", "
            << "area is " << rec.getArea();
    } else {
        out << rec.getTypeDescription();
    }
    return out;
}

int main(int argc, char const *argv[]) {
    CPoint p1(1, 5), p2(4, 1);
	p1.print();

    CRectangle rec1(p1, p2);
    cout << "length is " << rec1.getLength() << ", "
         << "width is " << rec1.getWidth() << ", "
         << "area is " << rec1.getArea() << endl;

    CPoint p3(2, -2), p4;
    CRectangle rec2(p4, p3);
    cout << rec2 << endl;

    CRectangle rec3(p3, p3);
    cout << rec3.getTypeDescription() << endl;
    cout << "the number of VALID rectangle: " << CRectangle::showCount() << endl;

    return 0;
}
